import NProgress from "@/utils/progress";
import type { AxiosRequestConfig, AxiosResponse } from "axios";
import type { CancelController } from "./cancel";
import { handleBusinessError, handleRequestError } from "./error-handler";
import type { HookSystem } from "./hooks";
import type { Logger } from "./logger";
import type { CustomRequestConfig } from "./types";

/**
 * 创建请求拦截器
 * @param cancelController 请求取消控制器
 * @param logger 日志系统
 * @param hooks 钩子系统
 * @param getToken 获取token的函数
 * @returns 请求拦截器
 */
export const createRequestInterceptor = (
  cancelController: CancelController,
  logger: Logger,
  hooks: HookSystem,
  getToken: () => string | null
) => {
  return {
    onFulfilled: async (config: AxiosRequestConfig) => {
      NProgress.start();

      const customConfig = config as CustomRequestConfig;

      // 添加 token
      if (!customConfig.skipTokenCheck) {
        const token = getToken();
        if (token) {
          customConfig.headers = customConfig.headers || {};
          customConfig.headers["Authorization"] = token;
        }
      }

      // 请求日志
      logger.logRequest(customConfig);

      // 添加到请求取消控制器
      cancelController.addRequest(customConfig);

      // 触发钩子
      return await hooks.triggerHook("beforeRequest", customConfig);
    },
    onRejected: (error: any) => {
      return Promise.reject(error);
    }
  };
};

/**
 * 创建响应拦截器
 * @param cancelController 请求取消控制器
 * @param logger 日志系统
 * @param hooks 钩子系统
 * @param clearToken 清除token的函数
 * @returns 响应拦截器
 */
export const createResponseInterceptor = (
  cancelController: CancelController,
  logger: Logger,
  hooks: HookSystem,
  clearToken: () => void
) => {
  return {
    onFulfilled: async (response: AxiosResponse) => {
      NProgress.done();
      try {
        // 从请求取消控制器中移除请求
        cancelController.removeRequestByConfig(
          response.config as CustomRequestConfig
        );

        // 响应日志
        logger.logResponse(response);

        // 触发钩子
        const processedResponse = await hooks.triggerHook(
          "afterResponse",
          response
        );

        // 处理业务逻辑错误，现在传入clearToken函数用于处理权限错误
        const customConfig = response.config as CustomRequestConfig;
        const { isError, error } = handleBusinessError(
          processedResponse,
          customConfig,
          clearToken
        );

        if (isError && error) {
          return Promise.reject(error);
        }

        const { data } = processedResponse;

        if (data && typeof data === "object") {
          // 调整业务成功的判断标准：code === 200 且 success === true
          const success =
            data.code === 200 &&
            (data.success === true || data.success === undefined);

          return {
            data: data.data,
            code: data.code,
            message: data.message,
            success, // 使用新的业务成功判断标准
            response: {
              status: response.status,
              statusText: response.statusText,
              headers: response.headers
            }
          };
        }

        return processedResponse;
      } catch (err) {
        // 防止响应处理过程中的错误直接暴露给用户
        logger.logError({
          message: "响应处理异常",
          name: "ResponseProcessError",
          config: response?.config
        });

        return Promise.reject({
          message: "响应数据处理异常",
          code: -1,
          config: {
            url: response?.config?.url,
            method: response?.config?.method
          }
        });
      }
    },
    onRejected: async (error: any) => {
      try {
        const customError = error;

        // 如果请求存在配置，从请求取消控制器中移除
        if (customError.config) {
          cancelController.removeRequestByConfig(
            customError.config as CustomRequestConfig
          );
        }

        // 错误日志
        logger.logError(customError);

        // 处理错误
        const processedError = await handleRequestError(error, clearToken);

        // 触发钩子
        const hookedError = await hooks.triggerHook("onError", processedError);

        return Promise.reject(hookedError);
      } catch (err) {
        // 防止错误处理过程中的异常直接暴露给用户
        logger.logError({
          message: "错误处理异常",
          name: "ErrorProcessError",
          code: -2
        });

        return Promise.reject({
          message: "请求失败",
          code: -1
        });
      }
    }
  };
};
